home *** CD-ROM | disk | FTP | other *** search
/ MacFormat 1997 July / macformat52.iso / mac / Shareware Plus / Developers / YAAF v1.0 alpha 1 / (Tools) / CompileVRes / viewformat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-04-15  |  11.2 KB  |  627 lines

  1. /*    viewformat.c
  2.  *
  3.  *        This contains the support routines used to handle the define
  4.  *    and view parsing routines
  5.  */
  6.  
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include "lex.h"
  11. #include "viewformat.h"
  12.  
  13. /************************************************************************/
  14. /*                                                                        */
  15. /*    Internal structures                                                    */
  16. /*                                                                        */
  17. /************************************************************************/
  18.  
  19. static struct ViewFormatRecord    *GViews;
  20. static FILE *GFile;
  21. extern int GFileFormat;
  22.  
  23. /************************************************************************/
  24. /*                                                                        */
  25. /*    Change Resolution                                                    */
  26. /*                                                                        */
  27. /************************************************************************/
  28.  
  29. /*    ChangeRes
  30.  *
  31.  *        Change resolution
  32.  */
  33.  
  34. static long ChangeRes(long x)
  35. {
  36.     if (GFileFormat == 0) return x;
  37.     else {
  38.         if ((x == -1) || (x == 0)) return x;
  39.         return (4*x)/3;
  40.     }
  41. }
  42.  
  43. /************************************************************************/
  44. /*                                                                        */
  45. /*    Swap Word/Long Word                                                    */
  46. /*                                                                        */
  47. /************************************************************************/
  48.  
  49. /*    SwapWord
  50.  *
  51.  *        Swap the order in a word
  52.  */
  53.  
  54. static short SwapWord(short x)
  55. {
  56.     unsigned char *t;
  57.     unsigned char tmp;
  58.     
  59.     if (GFileFormat) {
  60.         t = (unsigned char *)&x;
  61.         tmp = t[0];
  62.         t[0] = t[1];
  63.         t[1] = tmp;
  64.     }
  65.         
  66.     return x;
  67. }
  68.  
  69. /*    SwapLong
  70.  *
  71.  *        Swap the order in a long word
  72.  */
  73.  
  74. static long SwapLong(long x)
  75. {
  76.     unsigned char *t;
  77.     unsigned char tmp;
  78.     
  79.     if (GFileFormat) {
  80.         t = (unsigned char *)&x;
  81.         tmp = t[0];
  82.         t[0] = t[3];
  83.         t[3] = tmp;
  84.         tmp = t[1];
  85.         t[1] = t[2];
  86.         t[2] = tmp;
  87.     }
  88.         
  89.     return x;
  90. }
  91.  
  92. /************************************************************************/
  93. /*                                                                        */
  94. /*    Parser routines                                                        */
  95. /*                                                                        */
  96. /************************************************************************/
  97.  
  98. /*    FindViewDefine
  99.  *
  100.  *        Find the definition of this view
  101.  */
  102.  
  103. static ViewFormatRecord *FindViewFormat(long type)
  104. {
  105.     ViewFormatRecord *vf;
  106.     
  107.     for (vf = GViews; vf != NULL; vf = vf->next) {
  108.         if (vf->vtoken == type) return vf;
  109.     }
  110.     return NULL;
  111. }
  112.  
  113.  
  114. /*    ParseElement
  115.  *
  116.  *        This parses a single element in the 'define' definition
  117.  */
  118.  
  119. static ViewElemRecord *ParseElement(void)
  120. {
  121.     int i;
  122.     ViewElemRecord *ve;
  123.     
  124.     ve = (ViewElemRecord *)malloc(sizeof(ViewElemRecord));
  125.     if (ve == NULL) {
  126.         PrintError("out of memory");
  127.         exit(1);
  128.     }
  129.     
  130.     i = GetNextToken();
  131.     if (i == KTokenBool) {
  132.         ve->type = KViewBoolean;
  133.     } else if (i == KTokenInteger) {
  134.         ve->type = KViewInteger;
  135.     } else if (i == KTokenDimension) {
  136.         ve->type = KViewDimension;
  137.     } else if (i == KTokenString) {
  138.         ve->type = KViewString;
  139.     } else {
  140.         PrintError("Unknown element type: '%s'",GToken);
  141.         return NULL;
  142.     }
  143.     
  144.     i = GetNextToken();
  145.     if (i != ';') {
  146.         PrintError("Expected ';', got '%s'",GToken);
  147.         return NULL;
  148.     }
  149.     
  150.     return ve;
  151. }
  152.  
  153. /*    FlushEOR
  154.  *
  155.  *        Flush to the end of the record. This reads ahead until I hit
  156.  *    a 'create', 'define' or 'read' symbol
  157.  */
  158.  
  159. static void FlushEOR(void)
  160. {
  161.     int i;
  162.     
  163.     for (;;) {
  164.         i = GetNextToken();
  165.         if ((i == -1) || (i == KTokenCreate) || (i == KTokenDefine) || (i == KTokenRead)) break;
  166.     }
  167.     if (i != -1) PushBackToken(i);
  168. }
  169.  
  170. /*    ParseDefine
  171.  *
  172.  *        Parse a definition
  173.  */
  174.  
  175. static void ParseDefine(void)
  176. {
  177.     long l;
  178.     int i;
  179.     ViewFormatRecord *vf;
  180.     ViewElemRecord *ve;
  181.     ViewElemRecord *end;
  182.     
  183.     /*
  184.      *    Read in the header
  185.      */
  186.     
  187.     i = GetNextToken();
  188.     if (i != KLexString) {
  189.         PrintError("Expected type string, got '%s'",GToken);
  190.         FlushEOR();
  191.         return;
  192.     }
  193.     
  194.     l = *((long *)GToken);
  195.     if (FindViewFormat(l)) {
  196.         PrintError("View type \"%s\" already defined",GToken);
  197.         FlushEOR();
  198.         return;
  199.     }
  200.     
  201.     if ('{' != (i = GetNextToken())) {
  202.         PrintError("Expected '{', got '%s'",GToken);
  203.         FlushEOR();
  204.         return;
  205.     }
  206.     
  207.     vf = (ViewFormatRecord *)malloc(sizeof(ViewFormatRecord));
  208.     if (vf == NULL) {
  209.         PrintError("out of memory");
  210.         exit(1);
  211.     }
  212.     
  213.     /*
  214.      *    Parse the contents
  215.      */
  216.     
  217.     vf->vtoken = l;
  218.     vf->list = NULL;
  219.     vf->base = NULL;
  220.     
  221.     i = GetNextToken();
  222.     if (i == KTokenClass) {
  223.         /*
  224.          *    Class definition provided
  225.          */
  226.         
  227.         i = GetNextToken();
  228.         if (i != KLexString) {
  229.             PrintError("Expected type string, got '%s'",GToken);
  230.             FlushEOR();
  231.             return;
  232.         }
  233.         
  234.         l = *((long *)GToken);
  235.         if (NULL == (vf->base = FindViewFormat(l))) {
  236.             PrintError("View type \"%s\" not defined",GToken);
  237.             FlushEOR();
  238.             return;
  239.         }
  240.         
  241.         i = GetNextToken();
  242.         if (i != ';') {
  243.             PrintError("Expected ';', got '%s'",GToken);
  244.             FlushEOR();
  245.             return;
  246.         }
  247.     } else {
  248.         PushBackToken(i);
  249.     }
  250.     
  251.     /*
  252.      *    Read in the definition itself
  253.      */
  254.     
  255.     end = NULL;
  256.     for (;;) {
  257.         i = GetNextToken();
  258.         if (i == '}') break;
  259.         PushBackToken(i);
  260.         ve = ParseElement();
  261.     
  262.         if (ve == NULL) {
  263.             FlushEOR();
  264.             return;
  265.         }
  266.         
  267.         if (end) {
  268.             end->next = ve;
  269.         } else {
  270.             vf->list = ve;
  271.         }
  272.         end = ve;
  273.         ve->next = NULL;
  274.     }
  275.     
  276.     /*
  277.      *    Find terminating ';'
  278.      */
  279.     
  280.     i = GetNextToken();
  281.     if (i != ';') {
  282.         PrintError("Expected ';', got '%s'",GToken);
  283.         PushBackToken(i);
  284.     }
  285.     
  286.     vf->next = GViews;
  287.     GViews = vf;
  288. }
  289.  
  290. /************************************************************************/
  291. /*                                                                        */
  292. /*    Parse View Records                                                    */
  293. /*                                                                        */
  294. /************************************************************************/
  295.  
  296. /*    ParseArgument
  297.  *
  298.  *        Parse a simple argument
  299.  */
  300.  
  301. static int ParseArgument(ViewElemRecord *ve)
  302. {
  303.     int i;
  304.     long l;
  305.     unsigned char c;
  306.     short b;
  307.     
  308.     if (ve->type == KViewBoolean) {
  309.         i = GetNextToken();
  310.         if (i == KTokenTrue) {
  311.             b = 1;
  312.         } else if (i == KTokenFalse) {
  313.             b = 0;
  314.         } else {
  315.             PrintError("Expected 'true' or 'false' argument; got '%s'",GToken);
  316.             return -1;
  317.         }
  318.         b = SwapWord(b);
  319.         fwrite(&b,sizeof(b),1,GFile);
  320.     } else if (ve->type == KViewInteger) {
  321.         i = GetNextToken();
  322.         if (i == KLexInteger) {
  323.             l = SwapLong(GInteger);
  324.             fwrite(&l,sizeof(l),1,GFile);
  325.         } else {
  326.             PrintError("Expected integer, got '%s'",GToken);
  327.             return -1;
  328.         }
  329.     } else if (ve->type == KViewDimension) {
  330.         i = GetNextToken();
  331.         if (i == KLexInteger) {
  332.             l = SwapLong(ChangeRes(GInteger));
  333.             fwrite(&l,sizeof(l),1,GFile);
  334.         } else {
  335.             PrintError("Expected integer, got '%s'",GToken);
  336.             return -1;
  337.         }
  338.     } else if (ve->type == KViewString) {
  339.         i = GetNextToken();
  340.         if (i == KLexString) {
  341.             c = strlen(GToken);
  342.             fwrite(&c,1,1,GFile);
  343.             if (c) fwrite(GToken,c,1,GFile);
  344.             if ((c % 2) == 0) {
  345.                 c = 0;
  346.                 fwrite(&c,1,1,GFile);            /* Word align */
  347.             }
  348.         } else {
  349.             PrintError("Expected string, got '%s'",GToken);
  350.             return -1;
  351.         }
  352.     } else {
  353.         PrintError("Internal error");
  354.         return -1;
  355.     }
  356.     return 0;
  357. }
  358.  
  359. /*    ParseViewArgument
  360.  *
  361.  *        This parses the specified view record, writing it out to the
  362.  *    file. This barfs when it doesn't match; when I hit the end, I don't care
  363.  */
  364.  
  365. static int ParseViewArgument(ViewFormatRecord *vf)
  366. {
  367.     int i;
  368.     ViewElemRecord *ve;
  369.     
  370.     if (vf->base) {
  371.         if (ParseViewArgument(vf->base)) return -1;
  372.     }
  373.     for (ve = vf->list; ve != NULL; ve = ve->next) {
  374.         if (ParseArgument(ve)) return -1;
  375.         i = GetNextToken();                    /* Grab optional ',' */
  376.         if (i != ',') PushBackToken(i);
  377.     }
  378.     return 0;
  379. }
  380.  
  381. /*    ParseViewRecord
  382.  *
  383.  *        Given a 'view' keyword, this parses the contents
  384.  */
  385.  
  386. static long ParseViewRecord()
  387. {
  388.     ViewFormatRecord *vf;
  389.     int i;
  390.     long t;
  391.     long hoff;
  392.     ViewRecord vr;
  393.     ViewRecord nvr;
  394.     long noff;
  395.     long end;
  396.     
  397.     /*
  398.      *    Get the type
  399.      */
  400.     
  401.     i = GetNextToken();
  402.     if (i != KLexString) {
  403.         PrintError("Expected string, got '%s'",GToken);
  404.         return -1;
  405.     }
  406.     t = *((long *)GToken);
  407.     if (NULL == (vf = FindViewFormat(t))) {
  408.         PrintError("View \"%s\" not defined",GToken);
  409.         return -1;
  410.     }
  411.  
  412.     i = GetNextToken();
  413.     if (i != '{') {
  414.         PrintError("Expected '{', got '%s'",GToken);
  415.         return -1;
  416.     }
  417.     
  418.     /*
  419.      *    Now that we have the type, initialize and write out the
  420.      *    view header
  421.      */
  422.     
  423.     hoff = ftell(GFile);
  424.     vr.viewsize = SwapLong(0);
  425.     vr.viewchild = SwapLong(0);
  426.     vr.viewsibling = SwapLong(0);
  427.     vr.viewtype = SwapLong(t);
  428.     fwrite(&vr,sizeof(vr),1,GFile);
  429.     vr.viewsize = SwapLong(vr.viewsize);
  430.     vr.viewchild = SwapLong(vr.viewchild);
  431.     vr.viewsibling = SwapLong(vr.viewsibling);
  432.     
  433.     /*
  434.      *    Parse the arguments
  435.      */
  436.     
  437.     if (ParseViewArgument(vf)) return -1;
  438.     vr.viewsize = ftell(GFile) - hoff;
  439.     
  440.     /*
  441.      *    Now parse the subviews (if any)
  442.      */
  443.     
  444.     end = -1;
  445.     for (;;) {
  446.         i = GetNextToken();
  447.         if (i == '}') break;            /* No more subviews */
  448.         if (i == ',') continue;            /* Skip random ',' */
  449.         
  450.         if (i != KTokenView) {
  451.             PrintError("Expected view definition, got '%s'",GToken);
  452.             return -1;
  453.         }
  454.         
  455.         noff = ParseViewRecord();
  456.         if (noff == -1) return -1;
  457.         
  458.         /*
  459.          *    Attach to eol
  460.          */
  461.         
  462.         if (end == -1) {
  463.             vr.viewchild = noff - hoff;
  464.         } else {
  465.             /*
  466.              *    Attach to last child through sibling chain
  467.              */
  468.             
  469.             fseek(GFile,end,SEEK_SET);
  470.             fread(&nvr,sizeof(nvr),1,GFile);
  471.             nvr.viewsibling = SwapLong(noff - end);        /* To sibling */
  472.             fseek(GFile,end,SEEK_SET);
  473.             fwrite(&nvr,sizeof(nvr),1,GFile);
  474.             fseek(GFile,0L,SEEK_END);
  475.         }
  476.         end = noff;
  477.     }
  478.     
  479.     /*
  480.      *    Now that we've done the subview, update my own record
  481.      */
  482.     
  483.     fseek(GFile,hoff,SEEK_SET);
  484.     vr.viewsize = SwapLong(vr.viewsize);
  485.     vr.viewchild = SwapLong(vr.viewchild);
  486.     vr.viewsibling = SwapLong(vr.viewsibling);
  487.     fwrite(&vr,sizeof(vr),1,GFile);
  488.     fseek(GFile,0L,SEEK_END);
  489.     
  490.     /*
  491.      *    And return the file location where I am
  492.      */
  493.     
  494.     return hoff;
  495. }
  496.  
  497. /*    ParseCreate
  498.  *
  499.  *        Parse the create statement
  500.  */
  501.  
  502. static void ParseCreate(void)
  503. {
  504.     int i;
  505.     long l;
  506.     
  507.     i = GetNextToken();
  508.     if (i != KLexString) {
  509.         PrintError("Expected file name, got '%s'",GToken);
  510.         FlushEOR();
  511.         return;
  512.     }
  513.     
  514.     if (GFileFormat == 0) strcat(GToken,"_mac.vres");
  515.     else strcat(GToken,"_win.vres");
  516.     
  517.     GFile = fopen(GToken,"wb+");
  518.     if (GFile == NULL) {
  519.         PrintError("Unable to open '%s' for writing",GToken);
  520.         FlushEOR();
  521.         return;
  522.     }
  523.     printf("  Writing \"%s\"\n",GToken);
  524.     
  525.     i = GetNextToken();
  526.     if (i != KTokenView) {
  527.         PrintError("Expected 'view', got '%s'",GToken);
  528.         FlushEOR();
  529.         fclose(GFile);
  530.         return;
  531.     }
  532.     
  533.     ParseViewRecord();
  534.     
  535.     fclose(GFile);
  536.     
  537.     i = GetNextToken();
  538.     if (i != ';') {
  539.         PrintError("Expected ';', got '%s'",GToken);
  540.         PushBackToken(i);
  541.     }
  542. }
  543.  
  544.  
  545. /*    ParseRead
  546.  *
  547.  *        Parse the read command
  548.  */
  549.  
  550. static void ParseRead(void)
  551. {
  552.     int i;
  553.     char buffer[256];
  554.     
  555.     i = GetNextToken();
  556.     if (i != KLexString) {
  557.         PrintError("Expected file name, got '%s'",GToken);
  558.         FlushEOR();
  559.         return;
  560.     }
  561.     
  562.     strcpy(buffer,GToken);
  563.     i = GetNextToken();
  564.     if (i != ';') {
  565.         PrintError("Expected ';', got '%s'",GToken);
  566.         FlushEOR();
  567.     }
  568.     
  569.     ReadLexFile(buffer);
  570. }
  571.  
  572. /************************************************************************/
  573. /*                                                                        */
  574. /*    Main Parser Loop                                                    */
  575. /*                                                                        */
  576. /************************************************************************/
  577.  
  578. /*    ParseFile
  579.  *
  580.  *        Parse this file
  581.  */
  582.  
  583. void ParseFile(char *f)
  584. {
  585.     int i;
  586.     ViewFormatRecord *vf;
  587.     ViewElemRecord *ve;
  588.     
  589.     /* Clear the current pointer */
  590.     GViews = NULL;
  591.     
  592.     /* initialize lex engine */
  593.     InitLexEngine();
  594.     ReadLexFile(f);
  595.     
  596.     /* Parse the file */
  597.     for (;;) {
  598.         i = GetNextToken();
  599.         if (i == KTokenDefine) ParseDefine();
  600.         else if (i == KTokenCreate) ParseCreate();
  601.         else if (i == KTokenRead) ParseRead();
  602.         else if (i == -1) break;
  603.         else {
  604.             PrintError("Unexpected token '%s'",GToken);
  605.             FlushEOR();
  606.         }
  607.     }
  608.     
  609.     /* Done */
  610.     EndLexEngine();
  611.     
  612.     /* Release memory */
  613.     while (GViews) {
  614.         vf = GViews;
  615.         GViews = GViews->next;
  616.         
  617.         while (vf->list) {
  618.             ve = vf->list;
  619.             vf->list = ve->next;
  620.             
  621.             free((void *)ve);
  622.         }
  623.         
  624.         free((void *)vf);
  625.     }
  626. }
  627.